package com.spvs.approval.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.reflect.TypeToken;
import com.spvs.approval.domain.ApprovalClassifyEntity;
import com.spvs.approval.domain.ApprovalFromEntity;
import com.spvs.approval.domain.ApprovalSubmitEntity;
import com.spvs.approval.domain.ApprovalType;
import com.spvs.approval.domain.vo.ApprovalClassifyVo;
import com.spvs.approval.domain.vo.ApprovalFromVo;
import com.spvs.approval.domain.vo.ApprovalSubmitVo;
import com.spvs.approval.mapper.ApprovalFromMapper;
import com.spvs.approval.mapper.ApprovalSubmitMapper;
import com.spvs.approval.service.ApprovalClassifyService;
import com.spvs.approval.service.ApprovalFromService;
import com.spvs.approval.service.ApprovalSubmitService;
import com.spvs.approval.support.ApprovalBusinessContext;
import com.spvs.approval.utils.GsonUtils;
import com.spvs.common.core.constant.Constants;
import com.spvs.common.core.constant.SecurityConstants;
import com.spvs.common.core.domain.R;
import com.spvs.common.core.web.domain.AjaxResult;
import com.spvs.common.security.utils.SecurityUtils;
import com.spvs.system.api.IEquipNoticeService;
import com.spvs.system.api.ISysUserAutographService;
import com.spvs.system.api.RemoteUserService;
import com.spvs.system.api.domain.EquipNotice;
import com.spvs.system.api.domain.SysDept;
import com.spvs.system.api.domain.SysUser;
import com.spvs.system.api.domain.SysUserAutographAPI;
import com.spvs.system.api.model.LoginUser;
import io.jsonwebtoken.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Type;
import java.util.*;

@Slf4j
@Service("approvalFromService")
@Transactional
public class ApprovalFromServiceImpl extends ServiceImpl<ApprovalFromMapper, ApprovalFromEntity> implements ApprovalFromService {

    @Autowired
    private ApprovalSubmitService basicApprovalSubmitService;

    @Autowired
    private ApprovalSubmitMapper basicApprovalSubmitDao;

    @Autowired
    private ApprovalClassifyService basicApprovalClassifyService;
    @Autowired
    private ApprovalBusinessContext approvalBusinessContext;
    @Autowired
    private RemoteUserService userService;
    @Autowired
    private ISysUserAutographService sysUserAutographService;
    @Autowired
    private IEquipNoticeService equipNoticeService;
    @Qualifier("approvalFromMapper")
    @Autowired
    private ApprovalFromMapper approvalFromMapper;

    /**
     * 发起审批功能，用户发起审批使用
     * 1. 如果状态是非开始，那么可以修改审批信息
     * 2. 如果已经在审批中，不能发起审批信息
     * 3. 如果状态是201，表示要发起审批
     *
     * @param fromVo
     * @return
     */
    @Override
    public AjaxResult initiateApproval(ApprovalFromVo fromVo) {
        // 获取表单信息
        ApprovalFromEntity from = new ApprovalFromEntity();
        long l = System.currentTimeMillis();
        // 如果是新增的审批
        from.setUpdateTime(l);
        if (null == fromVo.getId()) {
            from.setCreateTime(l);
            from.setCode("SP" + IdWorker.getIdStr());
            from.setCreateUserId(fromVo.getCreateUserId());
            from.setCreateUserName(fromVo.getCreateUserName());
            from.setBusinessId(fromVo.getBusinessId());
            from.setDataStatus(ApprovalFromVo.APPROVAL_DATA_STATUS_EFFECTIVE);
            from.setType(fromVo.getType());
            from.setCodes(fromVo.getCodes());
            from.setBusJson(GsonUtils.ObjectToString(fromVo.getBusJsonMap()));
        } else {
            from = this.getById(fromVo.getId());
            // 如果该表单已经开始发起审批那么,不允许进行修改
            if (ApprovalFromVo.APPROVAL_STATUS_IN_PROGRESS <= from.getStatus()) {
                return AjaxResult.error(-1, "操作失败，审批单已经开始审批");
            }
        }
        ApprovalClassifyEntity classify = basicApprovalClassifyService.getById(fromVo.getClassifyId());
        ApprovalClassifyVo.JsonMap jsonMap = GsonUtils.bulidGson().fromJson(classify.getRuleShow(), ApprovalClassifyVo.JsonMap.class);
        if (jsonMap==null){
            return AjaxResult.error(-1, "审批分类规则为空");
        }
        from.setTemplateJson(GsonUtils.ObjectToString(jsonMap.getNodeMap()));
        from.setTitle(fromVo.getTitle());
        from.setContent(fromVo.getContent());
        from.setImgUrl(fromVo.getImgUrl());
        from.setStatus(fromVo.getStatus());
        from.setClassifyId(fromVo.getClassifyId());
        // TODO 判断该业务单是否已经审批，如果已经审批了，那么不能进行发起审批
        this.saveOrUpdate(from);
        // 如果审批状态是审批中， 那么发起审批
        if (ApprovalFromVo.APPROVAL_STATUS_IN_PROGRESS.equals(fromVo.getStatus())) {
            List<ApprovalSubmitEntity> submints = analysisAndApproval(from, jsonMap.getNodeMap(), null);
            this.updateById(from);
            approvalBusinessContext.businessCall(from.getType(), from, -1, null);
        }
        return AjaxResult.success();
    }

    /**
     * 修改审批信息，修改标题 、 内容
     *
     * @param approvalFromVo
     * @return
     */
    @Override
    public AjaxResult updateApproval(ApprovalFromVo approvalFromVo) {
        ApprovalFromEntity oldfrom = this.getById(approvalFromVo.getId());
        oldfrom.setUpdateTime(System.currentTimeMillis());
        // 如果不是完结表单，那么判断当前表单状态是否是未开始，如果已经开始审批那么不能进行修改
        if (ApprovalFromVo.APPROVAL_STATUS_IN_PROGRESS > oldfrom.getStatus()) {
            oldfrom.setTitle(approvalFromVo.getTitle());
            oldfrom.setContent(approvalFromVo.getContent());
            oldfrom.setImgUrl(approvalFromVo.getImgUrl());
            oldfrom.setClassifyId(approvalFromVo.getClassifyId());
            ApprovalClassifyEntity classify = basicApprovalClassifyService.getById(approvalFromVo.getClassifyId());
            ApprovalClassifyVo.JsonMap jsonMap = GsonUtils.bulidGson().fromJson(classify.getRuleShow(), ApprovalClassifyVo.JsonMap.class);
            oldfrom.setTemplateJson(GsonUtils.ObjectToString(jsonMap.getNodeMap()));
            this.updateById(oldfrom);
            return AjaxResult.success();
        } else {
            return AjaxResult.error(-1, "审批已经开始不能进行修改。");
        }
    }

    /**
     * 删除审批信息
     *
     * @param approvalFromVo
     * @return
     */
    @Override
    public AjaxResult deleteApproval(ApprovalFromVo approvalFromVo) {
        // 删除表单信息
        if (null != approvalFromVo.getId()) {
            ApprovalFromEntity from = this.getById(approvalFromVo.getId());
            if (ApprovalFromVo.APPROVAL_STATUS_IN_PROGRESS <= from.getStatus()) {
                return AjaxResult.error(-1, "已经开始审批，不能进行删除");
            }
            from.setDataStatus(ApprovalFromVo.APPROVAL_DATA_STATUS_INVALID);
            this.updateById(from);
            LambdaQueryWrapper<ApprovalSubmitEntity> subqw = Wrappers.lambdaQuery();
            subqw.eq(ApprovalSubmitEntity::getFromId, from.getId());
            List<ApprovalSubmitEntity> list = basicApprovalSubmitService.list(subqw);
            list.forEach(item -> {
                item.setDataStatus(ApprovalSubmitVo.APPROVAL_DATA_STATUS_INVALID);
            });
            basicApprovalSubmitService.saveBatch(list);
        }
        ApprovalSubmitVo submit = approvalFromVo.getSubmit();
        if (null != submit && null != submit.getId()) {
            if (ApprovalSubmitVo.APPROVAL_STATUS_IN_PROGRESS <= submit.getApprovalStatus()) {
                return AjaxResult.error(-1, "已经开始审批，不能进行删除");
            }
            ApprovalSubmitEntity subminEntity = basicApprovalSubmitService.getById(submit.getId());
            subminEntity.setDataStatus(ApprovalSubmitVo.APPROVAL_DATA_STATUS_INVALID);
            basicApprovalSubmitService.updateById(subminEntity);
        }
        return AjaxResult.success();
    }


    /**
     * 用户审批
     * 1. 判断如果是驳回，那么审批单直接驳回，如果是通过判断该层级是否存在未进行审批的审批人信息，如果不存在继续下一环节
     * 1. 审批之后如果该节点审批已经完成，那么下发下级审批信息
     * 2. 如果没有下级审批，按类型调用回调方法
     *
     * @param approvalSubmitVo
     * @return
     */
    @Override
    public AjaxResult approval(ApprovalSubmitVo approvalSubmitVo) {
        ApprovalSubmitEntity oldSubmit = basicApprovalSubmitService.getById(approvalSubmitVo.getId());
        //判断如果审批状态已经完结 那么不能进行审核
        if (ApprovalSubmitVo.APPROVAL_STATUS_ADOPT <= oldSubmit.getApprovalStatus()) {
            return AjaxResult.error(-1, "审批已经完结");
        }
        oldSubmit.setUpdateTime(System.currentTimeMillis());
        oldSubmit.setApprovalStatus(approvalSubmitVo.getApprovalStatus());
        oldSubmit.setApprovalIdea(approvalSubmitVo.getApprovalIdea());
        oldSubmit.setSignatureUrl(approvalSubmitVo.getSignatureUrl());
        ApprovalFromEntity from = this.getById(oldSubmit.getFromId());
        if (ApprovalSubmitVo.APPROVAL_STATUS_ADOPT.equals(approvalSubmitVo.getApprovalStatus())) {
            //TODO  这里需要获取用户最新的签名照片
            // AjaxResult info = sysUserAutographService.getInfo(oldSubmit.getApprovalStaffId().longValue(),SecurityConstants.INNER);
            // if (info.isSuccess()){
            //     Map<String,Object> data1 = (Map<String, Object>) info.get("data");
            //     oldSubmit.setSignatureUrl(data1.get("fileUrl").toString());
            // }

        }
        basicApprovalSubmitService.updateById(oldSubmit);
        // 是否按类型回调方法
        Boolean isCallback = false;
        // 如果审批驳回，查询对应审批单，如果审批单当前状态是审批中那么更新审批单为驳回
        if (ApprovalSubmitVo.APPROVAL_STATUS_NOT_PASSED.equals(approvalSubmitVo.getApprovalStatus())) {
            if (ApprovalFromVo.APPROVAL_STATUS_ADOPT > from.getStatus()) {
                from.setStatus(ApprovalFromVo.APPROVAL_STATUS_NOT_PASSED);
                this.updateById(from);
                isCallback = true;
            }
        }

        // 如果审批是通过，查询当下已经有的所有审批信息，如果所有的审批都通过那么下发下一级审批信，如果没有当前审批单通过
        if (ApprovalSubmitVo.APPROVAL_STATUS_ADOPT.equals(approvalSubmitVo.getApprovalStatus())) {
            LambdaQueryWrapper<ApprovalSubmitEntity> bqw = Wrappers.lambdaQuery();
            bqw.eq(ApprovalSubmitEntity::getFromId, oldSubmit.getFromId());
            List<ApprovalSubmitEntity> list = basicApprovalSubmitService.list(bqw);
            boolean isNextNode = true;
            for (Iterator<ApprovalSubmitEntity> iterator = list.iterator(); iterator.hasNext(); ) {
                ApprovalSubmitEntity next = iterator.next();
                if (!ApprovalFromVo.APPROVAL_STATUS_ADOPT.equals(next.getApprovalStatus())) {
                    isNextNode = false;
                }
            }
            // 判断如果是该节点最后一个通过的节点，下发下一节点审批信息到审批人
            if (isNextNode) {
                Type type = new TypeToken<Map<String, List<ApprovalClassifyVo.Node>>>() {
                }.getType();
                Map<String, List<ApprovalClassifyVo.Node>> nodeMap = GsonUtils.bulidGson().fromJson(from.getTemplateJson(), type);
                List<ApprovalSubmitEntity> submits = analysisAndApproval(from, nodeMap, oldSubmit.getApprovalSort());
                // 如果不存在下发的审批,审批单通过
                if (null == submits) {
                    from.setStatus(ApprovalFromVo.APPROVAL_STATUS_ADOPT);
                    isCallback = true;
                    this.updateById(from);
                }
            }
        }

        if (isCallback) {
            Map map = GsonUtils.bulidGson().fromJson(approvalSubmitVo.getBusinessJson(), Map.class);
            approvalBusinessContext.businessCall(from.getType(), from, oldSubmit.getApprovalSort(),oldSubmit.getApprovalStaffId().longValue());
        }
        // 如果审批通过不是最后一个审批节点，审批类型是 jsggs类型，那么调用回调方法
        if (!isCallback && oldSubmit.getApprovalStatus().equals(ApprovalSubmitVo.APPROVAL_STATUS_ADOPT ) && from.getType().equals(ApprovalBusinessContext.TYPE_JSGGS)){
            approvalBusinessContext.businessCall(from.getType(), from, oldSubmit.getApprovalSort(),oldSubmit.getApprovalStaffId().longValue());
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult queryByRecords(Integer id) {
        LambdaQueryWrapper<ApprovalSubmitEntity> qw = Wrappers.lambdaQuery();
        qw.eq(ApprovalSubmitEntity::getFromId, id);
        qw.eq(ApprovalSubmitEntity::getDataStatus, ApprovalSubmitVo.APPROVAL_DATA_STATUS_EFFECTIVE);
        qw.orderByAsc(ApprovalSubmitEntity::getApprovalSort);
        List<ApprovalSubmitEntity> list = basicApprovalSubmitService.list(qw);
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult queryApprovalByLaunch(Map<String, Object> param) {

        String pageSize = Optional.ofNullable(param.get("pageSize")).orElse(10).toString();
        String pageIndex = Optional.ofNullable(param.get("pageIndex")).orElse(1).toString();
        param.put("dataStatus", ApprovalFromVo.APPROVAL_DATA_STATUS_EFFECTIVE);
        String title = Optional.ofNullable(param.get("title")).orElse("").toString();
        String code = Optional.ofNullable(param.get("code")).orElse("").toString();
        LambdaQueryWrapper<ApprovalFromEntity> qw = Wrappers.lambdaQuery();
        if (null != param.get("approvalId")) {
            String userId = String.valueOf(param.get("approvalId"));
            qw.eq(ApprovalFromEntity::getCreateUserId, userId);
        }
        if (null != param.get("userId")) {
            String userId = String.valueOf(param.get("userId"));
            qw.eq(ApprovalFromEntity::getCreateUserId, Integer.valueOf(userId));
        }
        if (StringUtils.isNotBlank(title)) {
            qw.like(ApprovalFromEntity::getTitle, title);
        }

        if (StringUtils.isNotBlank(code)) {
            qw.like(ApprovalFromEntity::getCode, code);
        }
        if (null != param.get("businessId")) {
            String businessId = String.valueOf(param.get("businessId"));
            qw.like(ApprovalFromEntity::getBusinessId, businessId);
        }
        qw.eq(ApprovalFromEntity::getDataStatus, ApprovalSubmitVo.APPROVAL_DATA_STATUS_EFFECTIVE);
        qw.orderByDesc(ApprovalFromEntity::getUpdateTime);
        Page<ApprovalFromEntity> page = new Page<>(Integer.valueOf(pageIndex), Integer.valueOf(pageSize));
        qw.orderByDesc(ApprovalFromEntity::getCreateTime);
        page = this.page(page, qw);
        return AjaxResult.success(page);
    }

    @Override
    public AjaxResult queryApprovalBy(Map<String, Object> param) {
        if (null == param.get("approvalId")) {
            throw new RuntimeException("queryApprovalByLaunch  approvalId is null ");
        }
        String pageSize = Optional.ofNullable(param.get("pageSize")).orElse(10).toString();
        String pageIndex = Optional.ofNullable(param.get("pageIndex")).orElse(1).toString();
        param.put("dataStatus", ApprovalFromVo.APPROVAL_DATA_STATUS_EFFECTIVE);
        Page<ApprovalFromEntity> page = new Page<>(Integer.valueOf(pageIndex), Integer.valueOf(pageSize));
        basicApprovalSubmitDao.queryApprovalBy(page, param);
        return AjaxResult.success(page);
    }

    @Override
    public ApprovalFromEntity queryFromById(Integer id) {
        ApprovalFromEntity form = approvalFromMapper.selectById(id);
        if (form.getStatus() < ApprovalFromVo.APPROVAL_STATUS_ADOPT) {
            ApprovalSubmitEntity approvalSubmitEntity = basicApprovalSubmitDao.selectOne(new QueryWrapper<ApprovalSubmitEntity>().eq("from_id", id).eq("approval_staff_id", SecurityUtils.getUserId()).eq("approval_status", ApprovalSubmitVo.APPROVAL_STATUS_NOT_STARTED));
            if (null != approvalSubmitEntity) {
                form.setSubmitId(approvalSubmitEntity.getId());
                form.setSubmitStatus(approvalSubmitEntity.getApprovalStatus());
            }
        }
        return form;
    }

    /**
     * 按节点信息解析下一步走的流程
     *
     * @param nodeMap
     * @param lever
     * @return
     */
    public List<ApprovalSubmitEntity> analysisAndApproval(ApprovalFromEntity from, Map<String, List<ApprovalClassifyVo.Node>> nodeMap, Integer lever) throws RuntimeException {

        if (null == nodeMap || 0 == nodeMap.size()) {
            throw new RuntimeException("审批模板内容为空");
        }
        //  如果节点是空，默认-1  下级节点从0开始
        if (null == lever) {
            lever = -1;
        }
        int nextLever = lever + 1;
        String key = String.valueOf(nextLever);
        List<ApprovalClassifyVo.Node> nodes = nodeMap.get(key);
        if (null == nodes) {
            return null;
        }
        // 当下业务中审批节点只会选一个，节点类型审批人类型。
        ApprovalClassifyVo.Node node = nodes.get(0);
        from.setCurrentNodeId(node.getId());
        ApprovalClassifyVo.People people = node.getPeople();
        if (null == people) {
            throw new RuntimeException("审批人信息为空");
        }
        // 按当前部门  岗位  人 查询，如果人员id没有，那么按岗位查询，有多少人就下发多少审批


        // 按审批单标识查询最新的审批序号
        LambdaQueryWrapper<ApprovalSubmitEntity> aqw = Wrappers.lambdaQuery();
        aqw.eq(ApprovalSubmitEntity::getFromId, from.getId());
        int count = (int) basicApprovalSubmitService.count(aqw);
        List<ApprovalSubmitEntity> submits = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("userId", people.getUserId());
        R<LoginUser> userR = userService.getUserInfo(map, SecurityConstants.INNER);
        LoginUser data = userR.getData();


        if (userR.getCode() != Constants.SUCCESS || userR.getData() == null) {
            // 如果找不到人，跳到下级审批
            return analysisAndApproval(from, nodeMap, nextLever);
        }
        SysUser sysUser = data.getSysUser();
        sysUser.getDept();
        long l = System.currentTimeMillis();
        ApprovalSubmitEntity submit = new ApprovalSubmitEntity();
        submit.setFromId(from.getId());
        submit.setApprovalStatus(ApprovalSubmitVo.APPROVAL_STATUS_NOT_STARTED);
        submit.setApprovalStaffId(sysUser.getUserId().intValue());
        submit.setApprovalStaffName(sysUser.getUserName());
        submit.setApprovalDeptName(sysUser.getDept().getDeptName());
        submit.setDataStatus(ApprovalSubmitVo.APPROVAL_DATA_STATUS_EFFECTIVE);
        submit.setUpdateTime(l);
        submit.setCreateTime(new Date(l));
        submit.setContent(from.getContent());
        submit.setTitle(from.getTitle());
        submit.setImgUrl(from.getImgUrl());
        submit.setApprovalSort(count);
        submit.setCreateUser(from.getCreateUserName());
        submit.setCreateUserId(from.getCreateUserId());
        submit.setApprovalSort(nextLever);
        submits.add(submit);
        basicApprovalSubmitService.saveBatch(submits);
        //发送消息通知给当前待审批用户
        EquipNotice equipNotice = new EquipNotice();
        equipNotice.setTitle("审批通知");
        equipNotice.setContent("您收到一个《" + ApprovalType.getDescriptionByCode(from.getType()) + "》的审批，请及时查看");
        equipNotice.setState(0);
        equipNotice.setType(1L);
        equipNotice.setUserId(sysUser.getUserId());
        equipNotice.setDeptId(sysUser.getDeptId());
        equipNotice.setCreateTime(new Date(l));
        equipNotice.setRemark(from.getId().toString());
        equipNotice.setInfoExtend1(sysUser.getUserName());
        equipNoticeService.insertEquipNotice(equipNotice);
        return submits;
    }

}
